package com.riekoff.particlecubeworld.player;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import cc.creativecomputing.CCApp;
import cc.creativecomputing.control.CCControl;
import cc.creativecomputing.graphics.texture.CCTexture2D;
import cc.creativecomputing.graphics.texture.CCTexture3D;
import cc.creativecomputing.io.CCIOUtil;
import cc.creativecomputing.math.CCVector2f;
import cc.creativecomputing.math.CCVector3f;
import cc.creativecomputing.util.logging.CCLog;

public class APlayListController implements AGlobalTimingProgressListener{
	
	private static float DEFAULT_MOTAR = 0.3f;
	
	public class ATileFigure {
		
		private String _myFileName;
		
		private String _myZoneFile;
		private String _myPatternFile;
		private String _myColorFile;
		
		private int _myZoneIndex;
		private int _myPatternIndex;
		private int _myColorIndex;
		
		private float _myMotar;
		
		private int _myZoneAdd = 0;
		private int _myZoneMod = 5;
		
		private float _myFrameRate = 30;
		private float _myZoneScale = 1;

		private int _myHoldDuration = 1;
		private int _myBlendDuration = 1;
		private int _myBlendPreset = 0;

		
		public ATileFigure(String...theParameters){
			
			_myZoneFile = theParameters[0];
			_myPatternFile = theParameters[1];
			_myColorFile = theParameters[2];
			
			try{
				_myMotar = Float.parseFloat(theParameters[3]);
			}catch(Exception e){
				_myMotar = DEFAULT_MOTAR;
			}
			try{
				_myZoneMod = Integer.parseInt(theParameters[4]);
			}catch(Exception e){
			}
			try{
				_myZoneAdd = Integer.parseInt(theParameters[5]);
			}catch(Exception e){
			}
			try{
				_myZoneScale = Float.parseFloat(theParameters[6]);
				CCLog.info("_myZoneScale:" + _myZoneScale);
			}catch(Exception e){
			}
			try{
				_myFrameRate = Float.parseFloat(theParameters[7]);
			}catch(Exception e){
			}
			try{
				_myHoldDuration = Integer.parseInt(theParameters[8]);
			}catch(Exception e){
			}
			try{
				_myBlendDuration = Integer.parseInt(theParameters[9]);
			}catch(Exception e){}
			try{
				_myBlendPreset = Integer.parseInt(theParameters[10]);
			}catch(Exception e){
			}
			
			
		}
		
		public int zoneIndex(){
			return _myZoneIndex;
		}
		
		public int patternIndex(){
			return _myPatternIndex;
		}
		
		public int colorIndex(){
			return _myColorIndex;
		}
		
		public int holdDuration() {
			return _myHoldDuration;
		}
		
		public int blendDuration() {
			return _myBlendDuration;
		}
		
		public int blendPreset() {
			return _myBlendPreset;
		}
		
		public float motarBrightness(){
			return _myMotar;
		}
		
		public float zoneAdd(){
			return _myZoneAdd;
		}
		
		public float zoneMod(){
			return _myZoneMod;
		}
		
		public float zoneScale(){
			return _myZoneScale;
		}
		
		public float frameRate(){
			return _myFrameRate;
		}
	}
	
	@CCControl(name = "control direct")
	private boolean _cControlDirect = true;
	
	@CCControl(name = "list", min = 0, max = 20)
	private int _cList = 0;
	
	private int _myCurrentList = 0;
	
	private APatterns _myPatterns;
	private AColorMaps _myColorMaps;
	private AZones _myZones;
	
	private List<List<ATileFigure>> _myPlayLists = new ArrayList<>();
	
	public APlayListController(CCApp theApp){
		loadFromCSV(theApp,"data/playlists_csv");
	}
	
	public void loadFromFolder(CCApp theApp){
		_myPlayLists.clear();
		Map<String,Integer> myZoneFileIndexMap = new HashMap<>();
		Map<String,Integer> myPatternFileIndexMap = new HashMap<>();
		Map<String,Integer> myColorFileIndexMap = new HashMap<>();
		
		int myZoneFileCounter = 0;
		int myPatternFileCounter = 0;
		int myColorFileCounter = 0;
		
		for(String myPlayListFolder:CCIOUtil.list("data/playlists")){
			List<ATileFigure> myPlayList = new ArrayList<>();
			for(String myFile : CCIOUtil.list("data/playlists/" + myPlayListFolder, "txt") ){
				String myFigureFile = "data/playlists/" + myPlayListFolder + "/" + myFile;

				String[] myData = CCIOUtil.loadStrings(myFigureFile);
				ATileFigure myFigure = new ATileFigure(myData);
				
				if(!myZoneFileIndexMap.containsKey(myFigure._myZoneFile)){
					CCLog.info("zones:" + myFigure._myZoneFile);
					myZoneFileIndexMap.put(myFigure._myZoneFile, myZoneFileCounter);
					myZoneFileCounter++;
				}
				
				if(!myPatternFileIndexMap.containsKey(myFigure._myPatternFile)){
					CCLog.info("patterns:" + myFigure._myPatternFile);
					myPatternFileIndexMap.put(myFigure._myPatternFile, myPatternFileCounter);
					myPatternFileCounter++;
				}
				
				if(!myColorFileIndexMap.containsKey(myFigure._myColorFile)){
					CCLog.info("colors:" + myFigure._myColorFile);
					myColorFileIndexMap.put(myFigure._myColorFile, myColorFileCounter);
					myColorFileCounter++;
				}
				
				myFigure._myZoneIndex = myZoneFileIndexMap.get(myFigure._myZoneFile);
				myFigure._myPatternIndex = myPatternFileIndexMap.get(myFigure._myPatternFile);
				myFigure._myColorIndex = myColorFileIndexMap.get(myFigure._myColorFile);
				
				myPlayList.add(myFigure);
			}
			_myPlayLists.add(myPlayList);
		}
		
		String[] myZoneFiles = new String[myZoneFileCounter];
		String[] myPatternFiles = new String[myPatternFileCounter];
		String[] myColorFiles = new String[myColorFileCounter];
		
		CCLog.info("zones");
		for(String myZoneFile:myZoneFileIndexMap.keySet()){
			CCLog.info(myZoneFile);
			myZoneFiles[myZoneFileIndexMap.get(myZoneFile)] = myZoneFile;
		}
		CCLog.info("pattern");
		for(String myPatternFile:myPatternFileIndexMap.keySet()){
			CCLog.info(myPatternFile);
			myPatternFiles[myPatternFileIndexMap.get(myPatternFile)] = myPatternFile;
		}
		CCLog.info("colors");
		for(String myColorFile:myColorFileIndexMap.keySet()){
			CCLog.info(myColorFile);
			myColorFiles[myColorFileIndexMap.get(myColorFile)] = myColorFile;
		}

		_myZones = new AZones(myZoneFiles);
		_myPatterns = new APatterns(theApp.g, myPatternFiles);
		_myColorMaps = new AColorMaps(myColorFiles);
		
		int i = 0;
		for(List<ATileFigure> myPlayList:_myPlayLists){
			StringBuffer myCSV = new StringBuffer();
			myCSV.append("name,verlegemuster,farbschema,fugenhelligkeit 0 - 1,zonierung,zone clamp 0 - 5, zone offset 0 - 4, zone scale, zone frame rate\n");
			for(ATileFigure myFigure:myPlayList){
				myCSV.append(
//					myFigure._myFileName.substring(1) + "," +
					myFigure._myPatternFile.replaceAll("\\\\", "/") + "," +
					myFigure._myColorFile + "," +
					myFigure._myMotar + "," +
					myFigure._myZoneFile + "," +
					myFigure._myZoneMod + "," +
					myFigure._myZoneAdd + "," +
					myFigure._myZoneScale + "," +
					myFigure._myFrameRate + "\n"
				);
			}
//			CCIOUtil.saveStrings("playlists/" + i +".csv", myCSV.toString());
			System.out.println(myCSV);
		}
		
	}
	
	public void loadFromCSV(CCApp theApp, String theFile){
		_myPlayLists.clear();
		Map<String,Integer> myZoneFileIndexMap = new HashMap<>();
		Map<String,Integer> myPatternFileIndexMap = new HashMap<>();
		Map<String,Integer> myColorFileIndexMap = new HashMap<>();
		
		int myZoneFileCounter = 0;
		int myPatternFileCounter = 0;
		int myColorFileCounter = 0;

		
		for(String myPlayListCSV:CCIOUtil.list(theFile)){
			List<ATileFigure> myPlayList = new ArrayList<>();
			String[] myLines = CCIOUtil.loadStrings(theFile + "/" + myPlayListCSV);
			for(int i = 1; i < myLines.length;i++){
				String myLine = myLines[i];
				String[] myCSVData = myLine.split(",");
				
				ATileFigure myFigure;
				if (myCSVData.length<12) {
					myFigure = new ATileFigure(myCSVData[4], myCSVData[1], myCSVData[2], myCSVData[3], myCSVData[5], myCSVData[6], myCSVData[7], myCSVData[8], "1", "1", "1");
				}
				else {
					myFigure = new ATileFigure(myCSVData[4], myCSVData[1], myCSVData[2], myCSVData[3], myCSVData[5], myCSVData[6], myCSVData[7], myCSVData[8], myCSVData[9], myCSVData[10], myCSVData[11]);
				}
				if(!myZoneFileIndexMap.containsKey(myFigure._myZoneFile)){
//					CCLog.info("zones:" + myFigure._myZoneFile);
					myZoneFileIndexMap.put(myFigure._myZoneFile, myZoneFileCounter);
					myZoneFileCounter++;
				}
				
				if(!myPatternFileIndexMap.containsKey(myFigure._myPatternFile)){
//					CCLog.info("patterns:" + myFigure._myPatternFile);
					myPatternFileIndexMap.put(myFigure._myPatternFile, myPatternFileCounter);
					myPatternFileCounter++;
				}
				
				if(!myColorFileIndexMap.containsKey(myFigure._myColorFile)){
//					CCLog.info("colors:" + myFigure._myColorFile);
					myColorFileIndexMap.put(myFigure._myColorFile, myColorFileCounter);
					myColorFileCounter++;
				}
				
				myFigure._myZoneIndex = myZoneFileIndexMap.get(myFigure._myZoneFile);
				myFigure._myPatternIndex = myPatternFileIndexMap.get(myFigure._myPatternFile);
				myFigure._myColorIndex = myColorFileIndexMap.get(myFigure._myColorFile);
				CCLog.info(myFigure.zoneScale());
				myPlayList.add(myFigure);
			}
			_myPlayLists.add(myPlayList);
		}
		
		String[] myZoneFiles = new String[myZoneFileCounter];
		String[] myPatternFiles = new String[myPatternFileCounter];
		String[] myColorFiles = new String[myColorFileCounter];
		
//		CCLog.info("zones");
		for(String myZoneFile:myZoneFileIndexMap.keySet()){
//			CCLog.info(myZoneFile);
			myZoneFiles[myZoneFileIndexMap.get(myZoneFile)] = myZoneFile;
		}
//		CCLog.info("pattern");
		for(String myPatternFile:myPatternFileIndexMap.keySet()){
//			CCLog.info(myPatternFile);
			myPatternFiles[myPatternFileIndexMap.get(myPatternFile)] = myPatternFile;
		}
//		CCLog.info("colors");
		for(String myColorFile:myColorFileIndexMap.keySet()){
//			CCLog.info(myColorFile);
			myColorFiles[myColorFileIndexMap.get(myColorFile)] = myColorFile;
		}

		_myZones = new AZones(myZoneFiles);
		_myPatterns = new APatterns(theApp.g, myPatternFiles);
		_myColorMaps = new AColorMaps(myColorFiles);
	}
	
	public CCTexture3D zones(){
		return _myZones.texture();
	}
	
	public CCVector3f[] zoneInfos(){
		return _myZones.zoneInfos();
	}
	
	public CCVector2f[] patternDimensions(){
		return _myPatterns.dimension();
	}
	
	public CCTexture2D patterns(){
		return _myPatterns.texture();
	}
	
	public CCTexture2D colors(){
		return _myColorMaps.texture();
	}
	
	public int numberOfPlayLists(){
		return _myPlayLists.size();
	}

	public List<ATileFigure> playList(int theIndex){
		return _myPlayLists.get(theIndex);
	}

	@Override
	public void progress(float theProgress) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void update(float theDeltaTime) {
		// TODO Auto-generated method stub
	}
	
	public List<ATileFigure> currentList() {
		int myIndex = _myCurrentList;
		if(_cControlDirect){
			myIndex = _cList;
			myIndex %= _myPlayLists.size();
		}
		return _myPlayLists.get(myIndex);
	}
	
	
	public int[] getDurations() {
		
		int[] durations = new int[currentList().size()*2];
		for (int i=0; i<durations.length/2; i++) {
			durations[2*i]   = currentList().get(i).holdDuration();
			durations[2*i+1] = currentList().get(i).blendDuration();
		}
		return durations;
	}
	
	public int blendPreset (int theFigure) {
		try{
			return currentList().get(theFigure).blendPreset();
		}catch(Exception e){
			return 0;
		}
	}
	
	
	@Override
	public void onRestart() {
		_myCurrentList++;
		_myCurrentList %= _myPlayLists.size();
	}
}
